/**
 * 自定义操作日志记录装饰器
 */
import 'reflect-metadata';

// 声明Reflect元数据API的类型
declare global {
  namespace Reflect {
    function getMetadata(metadataKey: string, target: Object): any;
    function defineMetadata(metadataKey: string, metadataValue: any, target: Object): void;
    function hasMetadata(metadataKey: string, target: Object): boolean;
  }
}

// 业务类型（参考 com.ruoyi.common.enums.BusinessType）
export enum BusinessType {
  OTHER = 0,    // 其它
  INSERT = 1,   // 新增
  UPDATE = 2,   // 修改
  DELETE = 3,   // 删除
  GRANT = 4,    // 授权
  EXPORT = 5,   // 导出
  IMPORT = 6,   // 导入
  FORCE = 7,    // 强退
  GENCODE = 8,  // 生成代码
  CLEAN = 9     // 清空数据
}

// 操作人类别（参考 com.ruoyi.common.enums.OperatorType）
export enum OperatorType {
  OTHER = 0,    // 其它
  MANAGE = 1,   // 后台用户
  MOBILE = 2    // 手机端用户
}

// 操作状态（参考 com.ruoyi.common.enums.BusinessStatus）
export enum BusinessStatus {
  SUCCESS = 0,  // 成功
  FAIL = 1      // 失败
}

// 日志装饰器配置接口
export interface LogOptions {
  // 模块
  title: string;
  // 功能
  businessType?: BusinessType;
  // 操作人类别
  operatorType?: OperatorType;
  // 是否保存请求的参数
  isSaveRequestData?: boolean;
  // 是否保存响应的参数
  isSaveResponseData?: boolean;
  // 排除指定的请求参数
  excludeParamNames?: string[];
}

/**
 * 操作日志记录装饰器
 * @param options 日志配置
 */
export function Log(options: LogOptions): MethodDecorator {
  return (target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
    // 保存原始方法
    const originalMethod = descriptor.value;

    // 将日志配置保存到方法的元数据中
    if (!Reflect.hasMetadata('operation:log', target.constructor)) {
      Reflect.defineMetadata('operation:log', {}, target.constructor);
    }
    
    // 将配置保存到元数据中，供中间件使用
    const logs = Reflect.getMetadata('operation:log', target.constructor); 
    
    logs[propertyKey] = {
      title: options.title, 
      businessType: options.businessType || BusinessType.OTHER,
      operatorType: options.operatorType || OperatorType.MANAGE,
      isSaveRequestData: options.isSaveRequestData !== false, // 默认为true
      isSaveResponseData: options.isSaveResponseData !== false, // 默认为true
      excludeParamNames: options.excludeParamNames || []
    };
    
    Reflect.defineMetadata('operation:log', logs, target);
    
    // 为方法添加classReference属性，指向控制器类
    if (originalMethod) {
      originalMethod.classReference = target.constructor;
    }
    // 返回原始方法，日志记录由中间件处理
    return descriptor;
  };
}

export default Log; 